package cn.zymall.order.service.impl;

import cn.zymall.common.model.Order;
import cn.zymall.common.utils.redis.RedisUtil;
import cn.zymall.order.config.WxPayConfig;
import cn.zymall.order.dao.OrderMapper;
import cn.zymall.order.service.MyWxPayService;
import com.alibaba.fastjson.JSON;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: mall
 * @description: 微信支付实现类
 * @author: YueNiao
 * @email: 1486617253@qq.com
 * @create: 2020-08-21 20:31
 **/
@Service
public class MyWxPayServiceImpl implements MyWxPayService {
	@Autowired
	WxPayConfig wxPayConfig;
	@Autowired
	private com.github.binarywang.wxpay.service.WxPayService wxService;
	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private RedisUtil redisUtil;
	/**
	 * 发起微信订单
	 * @param request
	 * @return
	 * @throws WxPayException
	 */
	@Override
	public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request, Order order) throws WxPayException {
		order.setPayMode("微信");
		orderMapper.updateById(order);
		/**
		 * 校验redis中订单是否存在
		 */
		Order o = (Order) JSON.parse(redisUtil.get("order"+order.getOrderId())+"");
		if(o==null){
			//不存在修改订单状态为失效订单
			order.setOrderStatus((byte)9);
			orderMapper.updateById(order);
			return null;
		}
		return this.wxService.unifiedOrder(request);
	}

	/**
	 * 微信支付异步回调修改订单状态
	 * @param xmlData
	 * @throws WxPayException
	 */
	@Override
	public void wxNotify(String xmlData) throws WxPayException{
		final WxPayOrderNotifyResult notifyResult = this.wxService.parseOrderNotifyResult(xmlData);
		/**
		 * 删除redis中订单
		 */
		String tradNo=notifyResult.getOutTradeNo();
		Order redisOrder = (Order)JSON.parse(redisUtil.get("order"+tradNo)+"");
		if(redisOrder!=null){
			redisUtil.del("order"+tradNo);
		}

		Order o=new Order();
		o.setOrderId(tradNo);
		o.setOrderStatus((byte)2);
		o.setPayTime(new Date());

		orderMapper.updateById(o);
	}

	/**
	 * 查询订单
	 * @param orderId
	 * @return
	 */
	@Override
	public boolean searchWxOrder(String orderId) throws WxPayException {
		//查询订单是否支付完成
		Order order = orderMapper.selectById(orderId);
		if(order.getOrderStatus()!=1&&order.getOrderStatus()>0){
			return true;
		}
		WxPayOrderQueryResult wxPayOrderQueryResult = queryOrder(orderId);
		if("订单未支付".equals(wxPayOrderQueryResult.getTradeStateDesc())){
			return false;
		}else if("订单已支付".equals(wxPayOrderQueryResult.getTradeStateDesc())){
			return true;
		}
		return false;
	}

	/**
	 * 查询微信订单状态
	 * @param outTradeNo
	 * @return  tradeStateDesc：订单未支付  or tradeState NOTPAY
	 * @throws WxPayException
	 */
	public WxPayOrderQueryResult queryOrder(String outTradeNo)
			throws WxPayException {
		return this.wxService.queryOrder(null, outTradeNo);
	}

	/**
	 * 。
	 * @param order
	 * @return
	 * @throws Exception
	 */
	public Map<String, String> wxToPayUtil(Order order) throws Exception{

		//微信jdk提供的工具类
		Map<String,String> map=new ConcurrentHashMap<>();
		//公众号id
		map.put("appid", wxPayConfig.app_id);
		//商户号
		map.put("mch_id", wxPayConfig.mch_id);
		//随机字符串
		String noncestr = WXPayUtil.generateNonceStr();
		map.put("nonce_str",noncestr);
		//商品描述
		map.put("body",order.getSpuNorms());
		//商户订单号
		map.put("out_trade_no",order.getOrderId());
		//订单金额，单位为分，100表示1块钱
		BigDecimal money=order.getOrderMoney().multiply(new BigDecimal(100));
		map.put("total_fee",money+"");
		InetAddress localHost = InetAddress.getLocalHost();
		String hostAddress = localHost.getHostAddress();
		//服务器ip地址
		map.put("spbill_create_ip",hostAddress);
		//微信支付结果通知地址
		//map.put("notify_url",Config.notify_url);
		//先不设置
		map.put("notify_url","none");
		//交易类型
		map.put("trade_type","JSAPI");//MWEBH是5支付，NATIVE是Native支付，JSAPI是JSAPI支付（或小程序支付）
		//用户标示
		map.put("openid",order.getUserId()+"");
		//生成签名
		String signature = WXPayUtil.generateSignature(map, wxPayConfig.key, WXPayConstants.SignType.MD5);
		//签名
		map.put("sign",signature);

		//将map转成xml
		String requestXml = WXPayUtil.mapToXml(map);
		//得到的响应结果为xml格式
		String requestDataXml = doPostByXml("https://api.mch.weixin.qq.com/pay/unifiedorder", requestXml);
		Map<String, String> responseDataMap = WXPayUtil.xmlToMap(requestDataXml);
		return responseDataMap;
	}


	/**
	 * 转xml格式发送请求
	 * @param url
	 * @param requestXml
	 * @return
	 */
	public String doPostByXml(String url,String requestXml) {
		//创建post提交
		HttpPost httpPost=new HttpPost(url);
		//创建链接时的请求参数对象，并设置链接参数.
		RequestConfig requestConfig=RequestConfig.custom()
				//链接服务器主机超时时间
				.setConnectTimeout(15000)
				//链接请求超时时间
				.setConnectionRequestTimeout(60000)
				//设置读取响应数据超时时间
				.setSocketTimeout(60000)
				.build();
		//为httpPost请求设置参数
		httpPost.setConfig(requestConfig);
		//创建HttpClient链接对象
		CloseableHttpClient httpClient= HttpClients.createDefault();
		//将上传参数保存在entity属性中
		httpPost.setEntity(new StringEntity(requestXml,"UTF-8"));
		//添加头信息(告诉服务器参数类型为xml格式)
		httpPost.addHeader("content-Type","text/xml");
		String result="";
		try {
			//发送请求，httpClient执行post请求，并返回响应参数对象
			CloseableHttpResponse httpResponse=httpClient.execute(httpPost);
			//从响应对象中获取响应内容
			HttpEntity entity = httpResponse.getEntity();
			result= EntityUtils.toString(entity,"UTF-8");
		}catch (IOException e){
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 微信支付调用
	 * @param response
	 * @param order
	 * @return
	 */
	@Override
	public Map<String, String> wxToPay(HttpServletResponse response, Order order) {
		response.setCharacterEncoding("UTF-8");
		System.out.println(order);
		String prepayId = null;
		String sign = null;
		String noncestr = null;

		Map<String, String> stringStringMap = null;
		try {
			stringStringMap = wxToPayUtil(order);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("stringStringMap:" + stringStringMap);

		String returnCode = stringStringMap.get("return_code");
		String resultCode = stringStringMap.get("result_code");
		prepayId = stringStringMap.get("prepay_id");

		sign = stringStringMap.get("sign");

		noncestr = stringStringMap.get("nonce_str");
		System.out.println("结果状态码returnCode：" + returnCode);
		System.out.println("结果状态码resultCode：" + resultCode);
		System.out.println("prepayId:" + prepayId);
		System.out.println("sign:" + sign);
		System.out.println("noncestr:" + noncestr);

		Map<String, String> jsapiData = new HashMap<>();
		jsapiData.put("appId", wxPayConfig.app_id);
		jsapiData.put("package", "prepay_id=" + prepayId);
		jsapiData.put("signType", wxPayConfig.signType);
		jsapiData.put("nonceStr", WXPayUtil.generateNonceStr());
		jsapiData.put("timeStamp", System.currentTimeMillis() / 1000 + "");
		try {
			jsapiData.put("tosign", WXPayUtil.generateSignature(jsapiData, wxPayConfig.key));
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (null == prepayId) {
			return null;
		} else {
			return jsapiData;
		}
	}
}
